package code

import com.google.protobuf.GeneratedMessage
import com.google.protobuf.MessageLite
import common.Message
import common.ServerAttributeKey
import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.ByteToMessageDecoder
import org.slf4j.LoggerFactory
import utils.ByteUtils

/**
 * 二进制转成mymessage
 * @author King
 */
class PBBytesToMessageDecode : ByteToMessageDecoder() {

    private lateinit var messageManager: IMessageManager<GeneratedMessage, MessageLite>


    fun setMessageManager(messageManager: IMessageManager<GeneratedMessage, MessageLite>) {
        this.messageManager = messageManager
    }

    @Throws(Exception::class)
    override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf,
                        out: MutableList<Any>) {
        try {
            if (!msg.isReadable)
                return
            val channel = ctx.channel()
            val myMsg = Message.newMessage()
            val lenth = ByteUtils.readVariaInt(msg)
            val avalable = msg.readableBytes()
            myMsg.setmId(ByteUtils.readVariaInt(msg))
            myMsg.sethId(ByteUtils.readVariaInt(msg))
            myMsg.responseId = ByteUtils.readVariaInt(msg)
            val bodyLenth = lenth - avalable + msg.readableBytes()
            //错误了直接把channel关闭
            if (lenth >= Message.MAX_MESSAGE_SIZE) {
                log.error("解析字节码太长，长度:" + lenth + "modelId" + myMsg.getmId() + "action" + myMsg.gethId() + "ip:" + channel.remoteAddress())
                channel.close()
            }
            val attr = channel.attr(ServerAttributeKey.netChannel)
            attr?.let { myMsg.channel = it.get()  }
            if (bodyLenth != 0) {
                val bytes = ByteArray(bodyLenth)
                msg.readBytes(bytes)
                val lite = messageManager.getMessage(myMsg.getmId(), myMsg.gethId())
                if (lite != null) {
                    var builder: MessageLite.Builder = lite.newBuilderForType()
                    builder = builder.mergeFrom(bytes)
                    myMsg.setBody(builder.build())
                } else
                    log.error("没有获得对应的消息体moduleId:" + myMsg.getmId() + "actionId:" + myMsg.gethId() + "ip:" + channel.remoteAddress())
            }
            out.add(myMsg)
        } catch (e: Exception) {
            log.error("decode error" + "ip:" + ctx.channel().remoteAddress(), e)
            ctx.channel().close()
        }

    }

    companion object {
        private val log = LoggerFactory.getLogger(PBBytesToMessageDecode::class.java)
    }
}
